from typing import List, Dict, Optional
from dataclasses import dataclass
import json
import logging
from .one_api import ask

logger = logging.getLogger(__name__)

@dataclass
class WordDifficulty:
    frequency_rank: int      # 词频排名
    difficulty_level: str    # 难度等级 (A1-C2)
    exam_categories: List[str]  # 考试类别 (IELTS, TOEFL等)

@dataclass
class MemoryTips:
    etymology: str       # 词源分析
    word_parts: str     # 词根词缀
    association: str    # 联想记忆
    mnemonic: str       # 记忆技巧

@dataclass
class WordComparison:
    word: str           # 对比词
    difference: str     # 词义差别
    usage: str          # 使用场合
    example: str        # 示例

@dataclass
class WordDefinition:
    word: str
    phonetic: str
    pos: str
    definition: str
    examples: List[Dict[str, str]]
    difficulty: Optional[WordDifficulty] = None
    memory_tips: Optional[MemoryTips] = None
    comparisons: Optional[List[WordComparison]] = None

class DictionaryService:
    def __init__(self, model="gpt-4o"):
        self.model = model
        
    def _clean_json_response(self, response: str) -> str:
        """清理API返回的JSON字符串"""
        # 移除markdown代码块标记
        response = response.strip()
        if response.startswith('```json'):
            response = response[7:]
        elif response.startswith('```'):
            response = response[3:]
        if response.endswith('```'):
            response = response[:-3]
        return response.strip()
        
    def lookup_word(self, word: str) -> WordDefinition:
        """查询单词的详细信息"""
        prompt = f"""请按照以下 JSON 格式返回单词 "{word}" 的详细信息：
{{
    "word": "{word}",
    "phonetic": "音标",
    "pos": "词性",
    "definition": "中文释义",
    "examples": [
        {{"en": "英文例句1", "cn": "中文翻译1"}},
        {{"en": "英文例句2", "cn": "中文翻译2"}},
        {{"en": "英文例句3", "cn": "中文翻译3"}}
    ],
    "difficulty": {{
        "frequency_rank": 1234,
        "difficulty_level": "B1",
        "exam_categories": ["IELTS", "TOEFL", "CET4"]
    }},
    "memory_tips": {{
        "etymology": "词源分析",
        "word_parts": "词根词缀分析",
        "association": "相关联想",
        "mnemonic": "记忆技巧"
    }},
    "comparisons": [
        {{
            "word": "近义词1",
            "difference": "词义差别说明",
            "usage": "使用场合说明",
            "example": "对比示例"
        }}
    ]
}}

注意：
1. 直接返回 JSON 格式
2. 不要添加其他说明文字
3. 确保返回的是有效的 JSON
4. 词频排名范围 1-10000
5. 难度等级包括 A1, A2, B1, B2, C1, C2
6. 考试类别包括常见英语考试"""
        
        try:
            response = ask(prompt, self.model)
            cleaned_response = self._clean_json_response(response)
            data = json.loads(cleaned_response)
            
            # 创建 WordDifficulty 对象
            difficulty = WordDifficulty(**data.get('difficulty', {})) if 'difficulty' in data else None
            
            # 创建 MemoryTips 对象
            memory_tips = MemoryTips(**data.get('memory_tips', {})) if 'memory_tips' in data else None
            
            # 创建 WordComparison 对象列表
            comparisons = [WordComparison(**comp) for comp in data.get('comparisons', [])] if 'comparisons' in data else None
            
            # 创建主对象
            return WordDefinition(
                word=data['word'],
                phonetic=data['phonetic'],
                pos=data['pos'],
                definition=data['definition'],
                examples=data['examples'],
                difficulty=difficulty,
                memory_tips=memory_tips,
                comparisons=comparisons
            )
            
        except Exception as e:
            logger.error(f"Error looking up word '{word}': {str(e)}")
            raise ValueError(f"Failed to lookup word: {str(e)}")
    
    def get_related_words(self, word: str) -> List[str]:
        """获取相关词汇"""
        prompt = f"""
        请为单词 "{word}" 提供以下相关词汇：
        1. 同义词
        2. 反义词
        3. 相关词组
        
        请以JSON格式返回，格式如下：
        {{
            "synonyms": ["同义词1", "同义词2"],
            "antonyms": ["反义词1", "反义词2"],
            "phrases": ["词组1", "词组2"]
        }}
        """
        
        try:
            response = ask(prompt, self.model)
            return json.loads(response)
        except Exception as e:
            raise ValueError(f"Failed to get related words: {str(e)}") 